#include "drv_ina3221.h"
#include "bsp_i2c1.h"


/* INA3221 电压电流检测 */


/* 寄存器 */

#define INA_REG_CFG					0x00	//[R/W]
#define INA_REG_CH1_SHUNT_VOL		0x01	//[R]
#define INA_REG_CH1_BUS_VOL			0x02	//[R]
#define INA_REG_CH2_SHUNT_VOL		0x03	//[R]
#define INA_REG_CH2_BUS_VOL			0x04 	//[R]
#define INA_REG_CH3_SHUNT_VOL		0x05	//[R]
#define INA_REG_CH3_BUS_VOL			0x06	//[R]
#define INA_REG_CH1_CRIT_ALE_LIM	0x07	//[R/W] Channel-1 Critical-Alert Limit
#define INA_REG_CH1_WARN_ALE_LIM	0x08	//[R/W] channel-1 Warning-Alert Limit
#define INA_REG_CH2_CRIT_ALE_LIM	0x09	//[R/W]
#define INA_REG_CH2_WARN_ALE_LIM	0x0A	//[R/W]
#define INA_REG_CH3_CRIT_ALE_LIM	0x0B	//[R/W]
#define INA_REG_CH3_WARN_ALE_LIM	0x0C	//[R/W]
#define INA_REG_SHUNT_VOL_SUM		0x0D	//[R]
#define INA_REG_SHUNT_VOL_SUM_LIM	0x0E	//[R/W]
#define INA_REG_MASK_EN				0x0F	//[R/W]
#define INA_REG_PWR_UP_LIM			0x10	//[R/W]
#define INA_REG_PWR_LOW_LIM			0x11	//[R/W]
#define INA_REG_MAN_ID				0xFE	//[R] (0x5449)
#define INA_REG_DIE_ID				0xFF	//[R] (0x3220)


#define INA_CH_MAX      3
#define INA_SHUNT_RES_VALUE  (0.1)   // default shunt resistor value of 0.1 Ohm

#define INA_IIC_ADDR	0x80
// #define INA_IIC_ADDR	0x82




/* static func */

#define drv_ina_iic_start		bsp_i2c1_start
#define drv_ina_iic_stop		bsp_i2c1_stop
#define drv_ina_iic_ack			bsp_i2c1_ack
#define drv_ina_iic_noack		bsp_i2c1_noack
#define drv_ina_iic_wait_ack	bsp_i2c1_wait_ack
#define drv_ina_iic_write_byte	bsp_i2c1_write_byte
#define drv_ina_iic_read_byte	bsp_i2c1_read_byte_ack


//单个半字写入
static void drv_ina3221_write_reg(uint8_t reg, uint16_t data)
{
    bsp_i2c1_lock();

    drv_ina_iic_start();

    /* addr */
    drv_ina_iic_write_byte(INA_IIC_ADDR);
    drv_ina_iic_wait_ack();

    /* reg */
    drv_ina_iic_write_byte(reg);
    drv_ina_iic_wait_ack();

    /* data */
    drv_ina_iic_write_byte(data >> 8); //发送高字节
    drv_ina_iic_wait_ack();
    drv_ina_iic_write_byte(data & 0xFF); //发送低字节
    drv_ina_iic_wait_ack();

    drv_ina_iic_stop();

    bsp_i2c1_unlock();
}

//单个半字读取
static uint16_t drv_ina3221_read_reg(uint8_t reg)
{
    uint16_t ret = 0;

    bsp_i2c1_lock();

    drv_ina_iic_start();

    /* addr */
    drv_ina_iic_write_byte(INA_IIC_ADDR);
    drv_ina_iic_wait_ack();

    /* reg */
    drv_ina_iic_write_byte(reg);
    drv_ina_iic_wait_ack();

    /* data */
    drv_ina_iic_start();
    drv_ina_iic_write_byte(INA_IIC_ADDR | 0x01);
    drv_ina_iic_wait_ack();

    ret = drv_ina_iic_read_byte(); //发送高字节
    ret <<= 8;
    ret |= drv_ina_iic_read_byte(); //发送低字节
    drv_ina_iic_noack();

    drv_ina_iic_stop();

    bsp_i2c1_unlock();

    return ret;
}

/* export func */

/**
 * @brief 初始化
 * 
 */
void drv_ina3221_init(void)
{
    uint16_t id;
    _drv_ina_cfg_t cfg;

    bsp_i2c1_init();

    id = drv_ina3221_get_die_id();
    // printf("ina-id = 0x%X\r\n", id);
    if (id != 0x3220)
    {
        printf("INA3221 Error!\r\n");
    }

    cfg.cfg = 0;
    cfg.ch.rst = 0;
    cfg.ch.ch1_en = 1;
    cfg.ch.ch2_en = 1;
    cfg.ch.ch3_en = 1;
    cfg.ch.avg = INA_CFG_AVG_16;
    cfg.ch.vbus_ct = INA_CFG_CT_4P156MS;
    cfg.ch.vsh_ct = INA_CFG_CT_4P156MS;
    cfg.ch.mode = INA_CFG_MODE_SH_BUS_VOL_CON;
    drv_ina3221_set_config(cfg);
}

/**
 * @brief INA设置参数
 * 
 * @param cfg 
 */
void drv_ina3221_set_config(_drv_ina_cfg_t cfg)
{
    uint16_t data = 0x00;

    data = cfg.cfg;
    drv_ina3221_write_reg(INA_REG_CFG, data);
}

/**
 * @brief INA获取shunt分流电压,用于电流计算(原始数值) Full-scale=163.8mV, LSB=40uV, div=5uV
 * 
 * @param ch 通道[1-3]
 * @return uint16_t 
 */
uint16_t drv_ina3221_get_shunt_vol(uint8_t ch)
{
    uint16_t val;
    uint8_t reg;

    if (ch > INA_CH_MAX || ch == 0) return 0;
    ch--;
    reg = INA_REG_CH1_SHUNT_VOL + ch * 2;
    val = drv_ina3221_read_reg(reg);
    return val;
}

/**
 * @brief INA获取bus总线电压(原始数值) Full-Scale=32.76V, LSB=8mV, div=1mV
 *        最大测量范围32.76V, 但实际不能超过26V
 * 
 * @param ch 通道[1-3]
 * @return uint16_t 
 */
uint16_t drv_ina3221_get_bus_vol(uint8_t ch)
{
    uint16_t val;
    uint8_t reg;

    if (ch > INA_CH_MAX || ch == 0) return 0;
    ch--;
    reg = INA_REG_CH1_BUS_VOL + ch * 2;
    val = drv_ina3221_read_reg(reg);
    return val;
}

/**
 * @brief INA电压电流获取
 * 
 * @param ch 通道[1-3]
 * @param vol 电压(mV)
 * @param ele 电流(mA)
 */
void drv_ina3221_get_value(uint8_t ch, int16_t *vol, int16_t *ele)
{
	int16_t tmp;

	if (ch > INA_CH_MAX || ch == 0)
	{
		*vol = 0;
		*ele = 0;
		return ;
	}
    ch--;

	*vol = drv_ina3221_get_bus_vol(ch);	//电压
	tmp = drv_ina3221_get_shunt_vol(ch);	//电流
	*ele = tmp*5 / (INA_SHUNT_RES_VALUE*1000);
}

/**
 * @brief 获取ManufactureID (0x5449)
 *
 * @param idx
 * @return uint16_t
 */
uint16_t drv_ina3221_get_man_id(void)
{
    uint16_t id;

    id = drv_ina3221_read_reg(INA_REG_MAN_ID);
    return id;
}

/**
 * @brief 获取Die ID (0x3220)
 *
 * @return uint16_t
 */
uint16_t drv_ina3221_get_die_id(void)
{
    uint16_t id;

    id = drv_ina3221_read_reg(INA_REG_DIE_ID);
    return id;
}
